package org.example.clouddemo.service.common.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.example.clouddemo.bean.common.entity.User;
import org.example.clouddemo.bean.common.entity.UserWallet;
import org.example.clouddemo.bean.common.param.LoginParam;
import org.example.clouddemo.bean.common.param.RegisterParam;
import org.example.clouddemo.bean.common.vo.LoginResultVo;
import org.example.clouddemo.bean.common.vo.UserAppVo;
import org.example.clouddemo.service.common.UserService;
import org.example.clouddemo.service.common.mapper.UserMapper;
import org.example.clouddemo.service.common.mapper.UserWalletMapper;
import org.example.common.auth.JWTToken;
import org.example.common.auth.JWTUtils;
import org.example.common.auth.TokenService;
import org.example.common.bean.LoginUser;
import org.example.common.constants.RedisKey;
import org.example.common.exception.AppRunTimeException;
import org.example.common.utils.RedisUtil;
import org.example.common.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;


/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author hzg
 * @since 2025-06-06
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private PasswordEncoder passwordEncoder;


    @Autowired
    private TokenService tokenService;

    @Autowired
    private UserWalletMapper userWalletMapper;

    private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd/");
    /**
     * 图片保存路径
     */
    @Value("${file-save-path}")
    private String fileSavePath;
    @Override
    public IPage<User> selectPageVo(Page<User> page) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();

        queryWrapper.orderByDesc("create_time");
        return userMapper.selectPage(page, queryWrapper);
    }


    @Override
    public User selectOne(String username) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(User::getUsername, username);
        return userMapper.selectOne(queryWrapper);
    }

    @Override
    public int create(User user) {
        return userMapper.insert(user);
    }

    @Override
    public int update(User user) {
        return userMapper.updateById(user);
    }

    @Override
    public int delete(Long id,Boolean flag) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(User::getId, id);
        User user = new User();
        user.setEnableFlag(flag);

        user.setId(id);
        return userMapper.updateById(user);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long register(RegisterParam param, MultipartFile file, HttpServletRequest request) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(User::getUsername, param.getUsername());
        User user = userMapper.selectOne(queryWrapper);

        if (user != null) {
            throw new AppRunTimeException("已存在用户");
        }

        User addUser = new User();
        addUser.setId(IdUtil.getSnowflake().nextId());
        addUser.setUsername(param.getUsername());
        addUser.setUserType(LoginUser.USER_TYPE_APP);
        //密码加密
        addUser.setPassword(passwordEncoder.encode(param.getPassword()));
        // 新增字段
        addUser.setNickname(param.getNickname());

        addUser.setAvatarUrl(getUrl(file, request));
        //新建用户
        int i = userMapper.insert(addUser);
        UserWallet userWallet = new UserWallet();
        userWallet.setUserId(addUser.getId());
        userWallet.setBalance(BigDecimal.ZERO);
        userWalletMapper.insert(userWallet);
        return addUser.getId();
    }

    private String getUrl(MultipartFile file, HttpServletRequest request) {
        String directory = simpleDateFormat.format(new Date());
        /**
         * 文件保存目录 D:/images/
         * 如果目录不存在，则创建
         */
        File dir = new File(fileSavePath + directory);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        System.out.println("图片上传，保存的位置:" + fileSavePath + directory);

        /**
         * 给文件重新设置一个名字
         * 后缀
         */
        String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
        String newFileName = UUID.randomUUID().toString().replaceAll("-", "") + suffix;

        //4.创建这个新文件
        File newFile = new File(fileSavePath + directory + newFileName);
        //5.复制操作
        try {
            file.transferTo(newFile);
            //协议 :// ip地址 ：端口号 / 文件目录(/images/xxx.jpg)
            String url = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + "/images/" + directory + newFileName;
            System.out.println("文件上传，访问URL：" + url);
            return url;
        }catch (IOException e){
            throw new AppRunTimeException("文件上传失败");
        }
    }

    @Override
    public LoginResultVo login(LoginParam param) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(User::getUsername, param.getUsername());
        User user = userMapper.selectOne(queryWrapper);

        if (user == null) {
            throw new AppRunTimeException("用户不存在!");
        }
        if (!user.getEnableFlag()) {
            throw new AppRunTimeException("用户被禁用!");
        }

        //对比密码
        // 第一个参数 原密码   ,第二个参数  加密保存的密码  , 如果匹配, 结果返回true
        boolean isMatch = passwordEncoder.matches(param.getPassword(), user.getPassword());

        if (!isMatch) {
            throw new AppRunTimeException("密码错误!");
        }


        LoginResultVo loginResultVo = new LoginResultVo();


        LoginUser loginUser = new LoginUser();
        loginUser.setId(user.getId());
        loginUser.setUserName(user.getUsername());
        loginUser.setUserType(user.getUserType());
        loginUser.setLoginType(LoginUser.LOGIN_TYPE_PWD);

        String uuid = tokenService.createToken(loginUser);

        String loginUserJson = JSON.toJSONString(loginUser);

        //可以把 放在jwt token中
        JWTToken jwtToken = JWTUtils.getJWT(loginUserJson, uuid, "user", user.getUserType());
        loginResultVo.setUserId(user.getId());
        loginResultVo.setToken(jwtToken.getAccess_token());
        loginResultVo.setUserName(user.getUsername());
        loginResultVo.setNickName(user.getNickname());
        loginResultVo.setAvatarUrl(user.getAvatarUrl());
        loginResultVo.setAdmin(!LoginUser.USER_TYPE_APP.equals(user.getUserType()));


        //把用户信息 放在 redis上
        String key = RedisKey.TOKEN(user.getUserType(), uuid);
        //保存7天
        RedisUtil.set(key, loginUserJson, 7 * RedisUtil.TIME_DAYS_S);

        return loginResultVo;
    }

    @Override
    public UserAppVo getInfo(Long userId) {
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new AppRunTimeException("找不到数据!");
        }
        UserAppVo userAppVo = BeanUtil.copyProperties(user, UserAppVo.class);

        return userAppVo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean recharge(Long userId, BigDecimal amount) {
        UserWallet userWallet = userWalletMapper.selectById(userId);
        if (userWallet == null) {
            throw new AppRunTimeException("用户钱包不存在");
        }
        userWallet.setBalance(userWallet.getBalance().add(amount));
        return userWalletMapper.updateById(userWallet) > 0;
    }

    @Override
    public Boolean updateAvatar(MultipartFile file, HttpServletRequest request) {
        if (file == null || file.isEmpty()) {
            throw new IllegalArgumentException("上传文件不能为空");
        }
        String url = getUrl(file, request);
        User user = new User();
        // 获取用户信息
        LoginUser loginUser = SecurityUtils.getUserInfo();
        Long userId = loginUser.getId();
        user.setId(userId);
        user.setAvatarUrl(url);
        int i = userMapper.updateById(user);

        return i > 0;
    }
    @Override
    public Boolean updateNickname(String nickname) {
        if (StringUtils.isBlank(nickname)) {
            throw new IllegalArgumentException("昵称不能为空");
        }
        LoginUser loginUser = SecurityUtils.getUserInfo();
        Long userId = loginUser.getId();
        User user = new User();
        user.setId(userId);
        user.setNickname(nickname);

        return userMapper.updateById(user) > 0;
    }
}
